package cn.nbt.busManage.service.impl;

import cn.nbt.busManage.dao.mapper.UserMapper;
import cn.nbt.busManage.model.dto.RoleDto;
import cn.nbt.busManage.model.dto.UserDto;
import cn.nbt.busManage.model.entity.Role;
import cn.nbt.busManage.model.entity.User;
import cn.nbt.busManage.dao.repository.UserRepository;
import cn.nbt.busManage.service.UserService;
import jakarta.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional("mybatisTransactionManager")
public class IUserService implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private EntityManager entityManager;

    /**
     * 查询所有用户
     * @return List<User>
     */
    @Override
    public List<UserDto> findAll() {
        List<User> all = userMapper.findAll();
        ArrayList<UserDto> userDtos = new ArrayList<>();
        for (User user : all) {
            List<RoleDto> roleDtos = findRolesById(user.getId());
            UserDto userDto = new UserDto(user);
            userDto.setRoles(roleDtos);
            userDtos.add(userDto);
        }
        return userDtos;
    }

    /**
     * 根据userName查询用户
     * @param userName 用户userName
     * @return 用户信息
     */
    @Override
    public UserDto findByUserName(String userName) {
        User user = userMapper.findByUserName(userName);
        return user != null ? new UserDto(user) : null;
    }

    /**
     * 根据id查询用户
     * @param id 用户id
     * @return 用户信息
     */
    @Override
    public UserDto findById(Integer id) {
        User user = userMapper.findById(id);
        if (user == null) return null;
        List<RoleDto> rolesById = findRolesById(id);
        UserDto userDto = new UserDto(user);
        userDto.setRoles(rolesById);
        return userDto;
    }

    /**
     * 保存用户信息
     * @param userDto 用户信息
     * @return 保存结果
     */
    @Override
    @Transactional("transactionManager")
    public void save(UserDto userDto) {
        User user = new User();
        user.setId(userDto.getId());
        user.setUserName(userDto.getUserName());
        user.setPassword(userDto.getPassword());
        user.setEmail(userDto.getEmail());
        user.setPhone(userDto.getPhone());
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(null);
        /*List<RoleDto> roleDtoList = userDto.getRoles();
        ArrayList<Role> roles = new ArrayList<>();
        for (RoleDto roleDto : roleDtoList) {
            Role role = new Role();
            role.setId(roleDto.getId());
            role.setRoleName(roleDto.getRoleName());
            role.setStatus(roleDto.getStatus());
            roles.add(role);
        }
        user.setRoles(roles);*/
        userRepository.save(user);
        for (RoleDto roleDto : userDto.getRoles()) {
            addUserToRole(user.getId(), roleDto.getId());
        }
    }

    /**
     * 添加用户角色
     * @param userId 用户id
     * @param roleId 角色id
     */
    @Transactional("transactionManager")
    public void addUserToRole(Integer userId, Integer roleId) {
        // 查找学生和课程实体
        User user = entityManager.find(User.class, userId);
        Role role = entityManager.find(Role.class, roleId);
        user.addRole(role);
        entityManager.merge(user);
    }

    /**
     * 更新用户信息
     * @param userDto 用户信息
     * @return 更新结果
     */
    @Override
    public void update(UserDto userDto) {
        User user = new User();
        UserDto dto = findById(userDto.getId());
        user.setId(userDto.getId());
        user.setUserName(userDto.getUserName());
        user.setPassword(userDto.getPassword());
        user.setEmail(userDto.getEmail());
        user.setPhone(userDto.getPhone());
        user.setUpdateTime(LocalDateTime.now());
        user.setCreateTime(dto.getCreateTime());
//        更新中间表
        dto.getRoles().forEach(roleDto -> {
            removeRoleFromUser(userDto.getId(), roleDto.getId());
        });
        userMapper.updateUser(user.getUserName(),user.getId(),user.getUpdateTime(),user.getCreateTime(),user.getEmail(),user.getPassword(),user.getPhone());
        for (RoleDto roleDto : userDto.getRoles()) {
            addUserToRole(user.getId(), roleDto.getId());
        }
    }

    /**
     * 删除用户信息
     * @param id 用户id
     */
    @Override
    @Transactional("transactionManager")
    public void delete(Integer id) {
        for (RoleDto roleDto : findRolesById(id)) {
            removeRoleFromUser(id, roleDto.getId());
        }
        userRepository.deleteById(id);
    }

    /**
     * 移除用户角色
     * @param userId 用户id
     * @param roleId 角色id
     */
    @Transactional("transactionManager")
    public void removeRoleFromUser(Integer userId, Integer roleId) {
        User user = entityManager.find(User.class, userId);
        Role role = entityManager.find(Role.class, roleId);
        user.getRoles().remove(role);
        entityManager.merge(user);
    }



    /**
     * 根据用户名和密码查询用户
     * @param userName 用户名
     * @param password 密码
     * @return 用户信息
     */
    @Override
    public UserDto findByUserNameAndPassword(String userName, String password) {
        User user = userMapper.findByUserNameAndPassword(userName, password);
        if(user == null) return null;
        return new UserDto(user);
    }

    /**
     * 根据用户id查询角色列表
     * @param id 用户id
     * @return 角色列表
     */
    @Transactional("transactionManager")
    @Override
    public List<RoleDto> findRolesById(Integer id) {
        List<Role> roles = userRepository.findRolesById(id);
        ArrayList<RoleDto> roleDtos = new ArrayList<>();
        for (Role role : roles) {
            RoleDto roleDto = new RoleDto(role);
            roleDtos.add(roleDto);
        }
        return roleDtos;
    }

    /**
     * 根据信息查询用户
     * @param query 查询信息（名称或id）
     * @return 站点信息
     */
    @Override
    public List<UserDto> findByQuery(String query) {
        List<User> users = userMapper.findByQuery(query);
        if(users.isEmpty()) return null;
        List<UserDto> userDtos = new ArrayList<>();
        for (User user : users) {
            List<RoleDto> roles = findRolesById(user.getId());
            UserDto userDto = new UserDto(user);
            userDto.setRoles(roles);
            userDtos.add(userDto);
        }
        return userDtos;
    }
}

